/*
 *  OSXBGE.h
 *  OSXBGE
 *
 *  Created by Stafford Brunk on 2/6/09.
 *  Copyright 2009 Northpole Software. All rights reserved.
 */
 


#ifndef _OSXBGE_H
#define _OSXBGE_H

#include <IOKit/pci/IOPCIDevice.h>
#include <IOKit/network/IOEthernetController.h>
#include <IOKit/network/IOEthernetInterface.h>
#include <IOKit/network/IOGatedOutputQueue.h>
#include <IOKit/network/IOMbufMemoryCursor.h>
#include <IOKit/network/IOPacketQueue.h>
#include <IOKit/IOTimerEventSource.h>
#include <IOKit/IODeviceMemory.h>
#include <IOKit/IOFilterInterruptEventSource.h>
#include <IOKit/IOBufferMemoryDescriptor.h>
#include <IOKit/assert.h>

#include <sys/kpi_mbuf.h>
#include "BGE_REG.h"
#include "BGEHW_REG.h"

#define	BGE_IS_JUMBO_CAPABLE(sc)	((sc)->bge_flags & BGE_FLAG_JUMBO)
#define	BGE_IS_5700_FAMILY(sc)		((sc)->bge_flags & BGE_FLAG_5700_FAMILY)
#define	BGE_IS_5705_PLUS(sc)		((sc)->bge_flags & BGE_FLAG_5705_PLUS)
#define	BGE_IS_5714_FAMILY(sc)		((sc)->bge_flags & BGE_FLAG_5714_FAMILY)
#define	BGE_IS_575X_PLUS(sc)		((sc)->bge_flags & BGE_FLAG_575X_PLUS)

#define PCIM_MSICTRL_MSI_ENABLE         0x0001

#define NET_STAT(var, cnt) \
	do { (fNetStats->var) += (cnt); } while(0)

#define ETH_STAT(var, cnt) \
	do { (fEtherStats->var) += (cnt); } while(0)

#define OSXBGE com_northpolesoftware_driver_OSXBGE

#define ETHER_ADDR_LEN 6

/*
 * Adapter activation levels.
 */
enum {
    kActivationLevelNone = 0,  /* adapter shut off */
    kActivationLevelKDP,       /* adapter partially up to support KDP */
    kActivationLevelBSD        /* adapter fully up to support KDP and BSD */
};

/*
 * Periodic firing interval for the watchdog timer.
 */
enum {
    kWatchdogTimerPeriodMS = 4000
};

#define DEBUG	1

#ifdef  DEBUG
#warning ***************************************************
#warning ** DEBUG defined - turn off for deployment build **
#warning ***************************************************
#define DLOG(args...)  IOLog("-- OSXBGE --  "); IOLog(args); IOLog("\n");
#else
#define DLOG(args...)
#endif


class OSXBGE : public IOEthernetController
	{
		OSDeclareDefaultStructors( OSXBGE )	;
		
	public:
		virtual bool				start( IOService *provider );
		virtual void				stop ( IOService *provider );
		virtual void				free( void );
		
		virtual IOReturn			enable(  IONetworkInterface *netif );
		virtual IOReturn			disable( IONetworkInterface *netif );
		virtual IOReturn			enable(  IOKernelDebugger   *netif );
		virtual IOReturn			disable( IOKernelDebugger   *netif );
		
		virtual IOReturn			getHardwareAddress( IOEthernetAddress * address );
		virtual IOReturn			setHardwareAddress( const IOEthernetAddress * address);
		virtual IOReturn			setPromiscuousMode ( bool active);
		virtual IOReturn			setMulticastMode (bool active);
		virtual IOReturn			setMulticastList ( IOEthernetAddress *mcAddrList, UInt32 mcAddrCount);
		
		virtual IOOutputQueue *		createOutputQueue ( void );
		virtual bool				createWorkLoop( void );
		virtual IOWorkLoop *		getWorkLoop( void ) const;
		
		virtual bool				configureInterface( IONetworkInterface * interface );
		virtual IOReturn			selectMedium( const IONetworkMedium * medium );

		virtual const OSString *	newVendorString( void ) const;
		virtual const OSString *	newModelString( void ) const;
		
		virtual void				receivePacket( void * pkt_data, UInt32 * pkt_size, UInt32 timeoutMS );
		virtual UInt32				outputPacket(mbuf_t m, void * param);
		virtual void				getPacketBufferConstraints (IOPacketBufferConstraints * constraints) const;
		
		static void					interruptHandler (OSObject * target, IOInterruptEventSource * src, int count);
		static bool					interruptFilter (OSObject * target, IOFilterInterruptEventSource * src);
		static void					timeoutHandler (OSObject * target, IOTimerEventSource * src);
		void						timeoutOccurred (IOTimerEventSource * src);
		
		void						interruptOccurred( IOInterruptEventSource * src, int count );
		bool						receiveInterruptOccurred();
		void						transmitInterruptOccurred();
		
		//Transmit
		bool						allocateTxMemory( void );
		void						releaseTxMemory( void );
		bool						initTxRing ( void );
		void						freeTxRingPackets( void );
		void						serviceTxInterrupt( void );
		
		//Receive
		bool						allocateRxMemory( void );
		void						releaseRxMemory( void );
		bool						initRxRing ( void );
		void						freeRxRingPackets( void );
		void						serviceRxInterrupt( void );
		
		bool						setActivationLevel( UInt32 inLevel );
		bool						increaseActivationLevel( UInt32 inLevel );
		bool						decreaseActivationLevel( UInt32 inLevel );
		bool						resetCurrentActivationLevel( void );
		
		bool						initDriverObjects( IOService * provider );
		void						initPCIConfigSpace( IOPCIDevice * pci );
		
		//Ex-Macros
		void						BGE_SETBIT(struct bge_softc *sc, uint32_t reg, uint32_t x);
		void						BGE_CLRBIT(struct bge_softc *sc, uint32_t reg, uint32_t x);
		uint32_t					CSR_READ_4(struct bge_softc *sc, uint32_t reg);
		void						CSR_WRITE_4(struct bge_softc *sc, uint32_t reg, uint32_t val);
		void						PCI_SETBIT(UInt8 reg, UInt32 x);
		void						PCI_CLRBIT(UInt8 reg, UInt32 x);
		void						BGE_MEMWIN_WRITE(UInt32 x, UInt32 val);
		UInt32						BGE_MEMWIN_READ(UInt32 x);
		
		uint32_t					bge_readmem_ind(struct bge_softc *sc, int off);
		uint32_t					bge_readreg_ind(struct bge_softc *sc, int off);
		void						bge_writemem_direct(struct bge_softc *sc, int off, int val);
		void						bge_writemem_ind(struct bge_softc *sc, int off, int val);
		void						bge_writereg_ind(struct bge_softc *sc, int off, int val);
		void						bge_writembx(struct bge_softc *sc, int off, int val);
		int							bge_chipinit(struct bge_softc *sc);
		int							bge_reset();
		void						bge_setup(struct bge_softc *sc);
		
		//Mii Functions
		int							bge_miibus_writereg(struct bge_softc *sc, int phy, int reg, int val);
		int							bge_miibus_readreg(struct bge_softc *sc, int phy, int reg);
		
		
#define MBUF_PHYS_ADDR(m) ((IOPhysicalAddress)mbuf_data_to_physical(mbuf_data(m)))
		bool						updateRxDescriptor(UInt32 index);
		
		//These functions all deal with obtaining the MAC address
		int							bge_get_eaddr_nvram(struct bge_softc *sc, uint8_t ether_addr[]);
		int							bge_get_eaddr_fw(struct bge_softc *sc, uint8_t ether_addr[]);
		int							bge_get_eaddr_eeprom(struct bge_softc *sc, uint8_t ether_addr[]);
		int							bge_get_eaddr_mem(struct bge_softc *sc, uint8_t ether_addr[]);
		int							bge_get_eaddr(struct bge_softc *sc, uint8_t eaddr[]);
		uint8_t						bge_nvram_getbyte(struct bge_softc *sc, int addr, uint8_t *dest);
		int							bge_read_nvram(struct bge_softc *sc, caddr_t dest, int off, int cnt);
		int							bge_read_eeprom(struct bge_softc *sc, caddr_t dest, int off, int cnt);
		uint8_t						bge_eeprom_getbyte(struct bge_softc *sc, int addr, uint8_t *dest);
		uint32_t					CFSwapInt32(uint32_t arg);
		
		//Random other functions
		void						bge_stop_fw(struct bge_softc * sc);
		int							bge_wait_bit(struct bge_softc *sc, u_int32_t reg, u_int32_t bit, u_long timeout, const int clear);
		void						bge_cam_write(struct bge_softc *sc, u_char * data, int index);
		int							bge_blockinit(struct bge_softc *sc);
		
		//Needed for proper reset
		void						bge_sig_pre_reset(struct bge_softc *sc, int type);
		void						bge_sig_post_reset(struct bge_softc *sc, int type);
		void						bge_sig_legacy(struct bge_softc *sc, int type);
		
		//PHY Methods
		void						getPhyID();
		void						publishMedia();
		bool						_phyAddMediumType(UInt32 type, UInt32 speed, UInt32 index);
		bool						phySetMedium(mediumType_t medium);
		bool						phyReset(struct bge_softc *sc);
		IONetworkMedium *			_phyGetMediumWithType(UInt32 type);
		void						phyStatus();
		bool						phyWaitForAutoNegotiation();
		void						phyReportLinkStatus( bool firstPoll );
		mediumType_t				phyGetActiveMedium();
		int							phyBMCRReset(struct bge_softc *sc);
		
		bge_softc*					sc;
		
		IOPhysicalAddress			memBasePhysical;
		IOEthernetAddress           fEnetAddr;
		IOEthernetInterface *       fNetif;
		IOPCIDevice *               fPCIDevice;
		IOWorkLoop *                fWorkLoop;
		
		IOInterruptEventSource *    fInterruptSrc;
		IOOutputQueue *             fTransmitQueue;
		IOTimerEventSource *        fTimerSrc;
		IONetworkStats *            fNetStats;
		IOEthernetStats *           fEtherStats;
		IOMemoryMap *               fRegMap;
		OSDictionary *				fMediaDict;
		IONetworkMedium *			fMediaTable[0];
		
		/* Receive */
		IOMbufNaturalMemoryCursor *	fRxMbufCursor;
		IOBufferMemoryDescriptor *  fRxDescMemory;
		IOPhysicalAddress           fRxDescPhysAddr;
		bge_desc *					fRxDescBase;
		mbuf_t *                    fRxPacketArray;
		UInt32                      fRxHeadIndex;
		
		/* Transmit */
		IOMbufNaturalMemoryCursor *	fTxMbufCursor;
		IOBufferMemoryDescriptor *  fTxDescMemory;
		IOPhysicalAddress           fTxDescPhysAddr;
		bge_desc *					fTxDescBase;
		mbuf_t *                    fTxPacketArray;
		UInt32                      fTxDescBusy;
		UInt32                      fTxHeadIndex;
		UInt32                      fTxTailIndex;
		UInt32                      fTxRingDelayIOC;
		
		int							irq;
		UInt32						fPhyID;
		UInt16						fPhyPrevStatus;
		
		UInt32                      fActivationLevel;
		bool                        fEnabledForBSD;
		bool                        fEnabledForKDP;
		bool                        fSelectMediumOverride;
		bool                        fInterruptEnabled;
		mbuf_t						fKDPMbuf;
		IOPhysicalSegment			fKDPMbufSeg;
		
	};

#endif //_OSXBGE